#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;

class SelectServer
{
public:
    static const int N = sizeof(fd_set) * 8;
    static const int defaultfd = -1;
    // TCP工作
    void GetTcpsock(int port)
    {
        // 构建网络信息
        _serveraddr.sin_family = AF_INET;
        _serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
        _serveraddr.sin_port = htons(port);

        // 创建套接字
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            cout << "套接字创建失败" << endl;
            exit(-1);
        }
        cout << "套接字创建成功-sockfd:" << _listensockfd << endl;
        // 设置地址复用
        int opt = 1;
        setsockopt(_listensockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
        // 绑定
        int n = bind(_listensockfd, (struct sockaddr *)&_serveraddr, sizeof(_serveraddr));
        if (n < 0)
        {
            cout << "绑定失败" << endl;
            exit(-1);
        }
        cout << "绑定成功" << endl;
        // 设置监听状态
        static const int gbacklog = 8;
        n = listen(_listensockfd, gbacklog);
        if (n < 0)
        {
            cout << "监听状态设置失败" << endl;
        }
        cout << "监听状态设置成功" << endl;
    }

    SelectServer(int port)
    {
        GetTcpsock(port);
        // // 构建网络信息
        // _serveraddr.sin_family = AF_INET;
        // _serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
        // _serveraddr.sin_port = htons(port);

        // // 创建套接字
        // _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        // if (_listensockfd < 0)
        // {
        //     cout << "套接字创建失败" << endl;
        //     exit(-1);
        // }
        // cout << "套接字创建成功-sockfd:" << _listensockfd << endl;
        // // 设置地址复用
        // int opt = 1;
        // setsockopt(_listensockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
        // // 绑定
        // int n = bind(_listensockfd, (struct sockaddr *)&_serveraddr, sizeof(_serveraddr));
        // if (n < 0)
        // {
        //     cout << "绑定失败" << endl;
        //     exit(-1);
        // }
        // cout << "绑定成功" << endl;
        // // 设置监听状态
        // static const int gbacklog = 8;
        // n = listen(_listensockfd, gbacklog);
        // if (n < 0)
        // {
        //     cout << "监听状态设置失败" << endl;
        // }
        // cout << "监听状态设置成功" << endl;

        // 初始化读rfds的辅助数组
        for (int i = 0; i < N; i++)
        {
            _rfd_array[i] = defaultfd;
        }
        // 将监听套接字放到辅助数组中
        _rfd_array[0] = _listensockfd;
        // 打印_rfd_array数组
        cout << RfdsToString() << endl;
    }
    // listsockfd-获取连接
    void AcceptClient()
    {
        struct sockaddr_in clientaddr;
        socklen_t len = sizeof(clientaddr);
        int sockfd = accept(_listensockfd, (struct sockaddr *)&clientaddr, &len);
        if (sockfd < 0)
        {
            return;
        }
        cout << "服务端获取了一个新连接:fd:" << sockfd << "---[ip:" << inet_ntoa(clientaddr.sin_addr) << " port:" << ntohs(clientaddr.sin_port) << "]" << endl;
        // 将这个新获取的sockfd插入到_rfds_array中
        int pos = 0;
        for (; pos < N; pos++)
        {
            if (_rfd_array[pos] == defaultfd)
            {
                break;
            }
        }
        if (pos == N)
        {
            cout << "此服务器已经满载了,此fd关闭 fd:" << sockfd << endl;
            ::close(sockfd);
            // 打印_rfd_array数组
            cout << RfdsToString() << endl;
            return;
        }
        else
        {
            // 将此新fd插入到_rfd_array中
            _rfd_array[pos] = sockfd;
            cout << "fd:" << sockfd << "已被添加到_rfd_array中" << endl;
            // 打印_rfd_array数组
            cout << RfdsToString() << endl;
        }
    }
    // sockfd-通信IO
    void ServiceIO(int pos)
    {
        // 缓冲区
        char inbuffer[1024];
        ssize_t n = recv(_rfd_array[pos], inbuffer, sizeof(inbuffer), 0);
        if (n > 0)
        {
            // 读取成功
            inbuffer[n] = '\0';
            string send_str = "[Server Echo]#";
            send_str += inbuffer;
            cout << "获取到信息:" << inbuffer << endl;
            send(_rfd_array[pos], send_str.c_str(), send_str.size(), 0);
        }
        else if (n == 0)
        {
            // 客户端退出
            ::close(_rfd_array[pos]);
            cout << "客户端退出,fd:" << _rfd_array[pos] << "已被关闭" << endl;
            // 清空pos位置的有效的fd
            _rfd_array[pos] = defaultfd;
            // 打印_rfd_array数组
            cout << RfdsToString() << endl;
        }
        else
        {
            // 读取失败
            ::close(_rfd_array[pos]);
            cout << "读取失败,fd:" << _rfd_array[pos] << "已被关闭" << endl;
            // 清空pos位置的有效的fd
            _rfd_array[pos] = defaultfd;
            // 打印_rfd_array数组
            cout << RfdsToString() << endl;
        }
    }

    // 处理已就绪的rfds
    void HanderEvent(fd_set &rfds)
    {
        for (int i = 0; i < N; i++)
        {
            // 非法fd
            if (_rfd_array[i] == defaultfd)
            {
                continue;
            }
            // 合法fd
            // 判断有效fd
            if (FD_ISSET(_rfd_array[i], &rfds))
            {
                // 有效的fd
                // 判断是listensockfd还是sockfd
                if (_listensockfd == _rfd_array[i])
                {
                    // listensockfd
                    AcceptClient();
                }
                else
                {
                    // sockfd
                    ServiceIO(i);
                }
            }
        }
    }

    // 启动服务
    void Loop()
    {
        while (true)
        {
            fd_set rfds;    // 读文件描述符集合
            FD_ZERO(&rfds); // 清空
            int max_rfd = defaultfd;
            for (int i = 0; i < N; i++)
            {
                if (_rfd_array[i] == defaultfd)
                {
                    continue;
                }
                // 合法fd
                FD_SET(_rfd_array[i], &rfds);
                if (max_rfd < _rfd_array[i])
                {
                    max_rfd = _rfd_array[i];
                }
            }
            struct timeval timeout = {1, 0}; // 等待策略
            int n = select(max_rfd + 1, &rfds, nullptr, nullptr, &timeout);
            if (n < 0)
            {
                cout << "select函数错误" << endl;
            }
            else if (n == 0)
            {
                // cout << "当前没有rfd就绪 timeout:" << timeout.tv_sec << "." << timeout.tv_usec << endl;
            }
            else
            {
                cout << "当前已经有rfd就绪了 select返回值:" << n << endl;
                // 处理
                HanderEvent(rfds);
            }
        }
    }
    // 将所有的合法的fd输出到字符串中
    string RfdsToString()
    {
        string fdstr = "当前_rfd_array数组fd集合### ";
        for (int i = 0; i < N; i++)
        {
            if (_rfd_array[i] == defaultfd)
            {
                continue;
            }
            fdstr += to_string(_rfd_array[i]);
            fdstr += " ";
        }
        return fdstr;
    }

private:
    struct sockaddr_in _serveraddr; // server网络信息
    int _listensockfd;              // 监听套接字
    int _rfd_array[N];              // 读rfds的辅助数组
};